<?php
/**
 * BordomIRC module for PHP-IRC
 * Copyright (c) 2005-2006 Jason Hines <jason@greenhell.com>
 * $Rev: 1676 $
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

class bordom_mod extends module {

	public $title = "Bordom module";
	public $author = "oweff";
	public $version = "verbosity!2.2";
	private $channel = "#friskykittens";
        private $source = "friskykittens";
	private $password = "frisky";
	private $timespan = 300; // check every 5 minutes for new items
	private $client = null;
        private $timeout = 10; // timeout after 10 seconds

	// initialize the module on startup
	public function init() {
		// Include the Bordom API
		include_once('XML/RPC.php');
		$this->client = new XML_RPC_Client('/rpc/', 'bordom.net');
		$this->client->setCredentials($this->source, $this->password);

		// Update interval
		$this->timerClass->addTimer("bordom_mod_scanupdate", $this, "scan_update", "", $this->timespan, true);
	}

	// shutdown method
	public function destroy() {
		$this->timerClass->removeTimer("bordom_mod_scanupdate");
	}

	// runs once every interval
	public function scan_update($args) {
                $this->update_slogan();
                $this->announce_queued();
                $this->announce_comments();
                return true;
        }

        private function update_slogan() {
                // set slogan from channel topic
                $chanData = $this->ircClass->getChannelData($this->channel);
                $topic = $this->clean_string($chanData->topic);
                if (!empty($topic)) {
                    $this->ircClass->log("Updating slogan from channel topic...");
                    $params = array(new XML_RPC_Value($topic,'string'));
                    $this->ircClass->log("Topic is: {$topic}");
                    $msg = new XML_RPC_Message('brax.sources.setSlogan', $params);
                    $resp = $this->client->send($msg,$this->timeout);
                    if (!$resp) return true;
                    if ($resp->faultCode()) {
                        $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
                        return true;
                    }
                }
                return true;
        }

        private function announce_queued() {
                // check for newly queued items
                $this->ircClass->log("Scanning for new items in queue...");
        	$params = array('queued' => 1);
        	$msg = new XML_RPC_Message('brax.items.getItems',array(XML_RPC_Encode($params)));
        	$resp = $this->client->send($msg,$this->timeout);
        	if (!$resp) return true;
        	if ($resp->faultCode()) {
                        $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
        		return true;
                } else {
            	        $result = XML_RPC_Decode($resp->value());
        	    	$i=0;
                        foreach ($result['items'] as $item) {
        		        $this->ircClass->log("Found item: {$item['item_id']} Time: ".date("r",$item['time'])." Now: ".date("r",time()));
            			if ($item['time'] > (time()-$this->timespan) && $item['source'] != $this->source) {
        	    			$i++;
        		    		$_msg = "{$item['letter']}: \"{$item['title']}\" added by {$item['author']} (from {$item['source']})\n";
            				$this->ircClass->privMsg($this->channel, $_msg);
        	    		}
            		}
            		$this->ircClass->log("{$i} new items found in queue.");
                }
		return true;
	}

        private function announce_comments() {
                // check for recent comments
                $this->ircClass->log("Scanning for new comments...");
        	$msg = new XML_RPC_Message('brax.comments.recentComments');
        	$resp = $this->client->send($msg,$this->timeout);
        	if (!$resp) return true;
        	if ($resp->faultCode()) {
                        $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
        		return true;
                } else {
            	        $result = XML_RPC_Decode($resp->value());
                        foreach ($result as $comment) {
            			if ($comment['time'] > (time()-$this->timespan) && $comment['source'] != $this->source) {
                                        $this->ircClass->log("Announcing comment: {$comment['comment_id']}");
        		    		$_msg = "{$comment['letter']}: <{$comment['author']}> ". $this->clean_string($comment['text']) ." (Comment #".BOLD.$comment['comment_id'].BOLD." added)";
            				$this->ircClass->privMsg($this->channel, $_msg);
        	    		}
            		}
                }
		return true;
	}

	/**
      	 * Runs on every line in hub channel
	 */
	public function priv_parseline($line, $args) {
		$channel = $line['to'];
		$nick = $line['fromNick'];
		$host = $line['fromHost'];

		if ($channel == $this->ircClass->getNick()) {
			return;
		}
		if (!$this->ircClass->hasModeSet($channel, $line['fromNick'], "vo")) {
			return;
		}

		// check if line is a command
		if (preg_match("/^([a-zA-Z]|[0-9]+)[:]\s(.*)$/",$line['text'],$matches)) {
			if (preg_match("/^([a-zA-Z])$/",$matches[1],$tmp)) {
				// is a letter, get ID
                                $letter = strtolower($matches[1]);
				$params = array(new XML_RPC_Value($letter, 'string'));
				$msg = new XML_RPC_Message('brax.items.getIdByLetter', $params);
				$resp = $this->client->send($msg,$this->timeout);
                                if (!$resp) return true;
				if ($resp->faultCode()) {
                                        $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
					return;
				} else {
					$item_id = $resp->value()->scalarval();
				}
			} else {
				$item_id = $matches[1];
			}
			$param = trim($matches[2]);
			$parts = explode(" ",$param);
			$command = $parts[0];
			array_shift($parts);
			$extra = implode(" ",$parts);
			switch (strtolower($command)) {
				case "title":
				case "tit":
					$title = $this->clean_string($extra);
					$this->do_title($item_id,$nick,$title);
				break;
				case "nick":
				case "author":
					$author = $extra;
					$this->do_author($item_id,$nick,$author);
				break;
				case "caption":
				case "cap":
					$caption = $this->clean_string($extra);
					$this->do_caption($item_id,$nick,$caption);
				break;
				case "excerpt":
				case "exc":
					$excerpt = $this->clean_string($extra);
					$this->do_excerpt($item_id,$nick,$excerpt);
				break;
				case "image":
				case "img":
					$image = $extra;
					$this->do_image($item_id,$nick,$image);
				break;
				case "tag":
					$tag = $extra;
					$this->do_tag($item_id,$nick,$tag);
				break;
				case "group":
				case "set":
					$set = $extra;
					$this->do_set($item_id,$nick,$set);
				break;
				case "untag":
				case "deltag":
					$tag = $extra;
					$this->do_untag($item_id,$nick,$tag);
				break;
				case "url":
					$url = $extra;
					$this->do_url($item_id,$nick,$url);
				break;
				case "hide":
					$this->do_hide($item_id,$nick);
				break;
				case "show":
                case "unhide":
					$this->do_show($item_id,$nick);
				break;
				case "nsfw":
					$this->do_nsfw($item_id,$nick);
				break;
				case "sfw":
					$this->do_sfw($item_id,$nick);
				break;
				case "bump":
					$this->do_bump($item_id,$nick);
				break;
				case "info":
					$this->do_info($item_id,$nick);
				break;
				case "feature":
				case "feat":
					$this->do_feature($item_id,$nick);
				break;
				default:
                    // 1 word comments become tags
    				$comment = trim($command . " " . $extra);
	    			$parts = explode(" ",$comment);
					$this->do_comment($item_id,$nick,$comment);
				break;
			}
			return;
		}

		// line is not a command, does it contain items?
		preg_match_all("/.?(http[s]?:\/\/\S+)/i", $line['text'], $matches);
		$full = $matches[0];
		$char = substr($full[0],0,1);
		if ($char == "+" || $char == "~" || $char == "!") {
			if (strlen($full[0]) > 70 && $char != "+") {
		                $this->ircClass->log("Made tinyurl.");
				$longurl = substr($full[0],1);
				$tinyurl = file_get_contents("http://tinyurl.com/api-create.php?url={$longurl}");
				$this->ircClass->privMsg($this->channel, $tinyurl);			
			}
			return;
		}

		$matches = $matches[1];
		if (!empty($matches)) {
			// urls matched, submit them
			foreach ($matches as $url) {
				$this->do_submit($url,$nick,$host);
			}
			return;
		}

	}

	/**
	 * General commands
	 */
	public function priv_search($line, $args) {
		$channel = $line['to'];
		if ($channel == $this->ircClass->getNick()) {
			return;
		}
                if (!$this->ircClass->hasModeSet($channel, $line['fromNick'], "vo")) {
			return;
		}
		if ($args['nargs'] == 0) {
			$this->ircClass->notice($line['fromNick'], "You must specify a keyword to search.");
			return;
		}

                $phrase = trim($args['arg1']);
		$params = array(
                    'query'=>$phrase,
                    'queued'=>0,
                );
		$msg = new XML_RPC_Message('brax.items.getItems',array(XML_RPC_Encode($params)));
		$resp = $this->client->send($msg,$this->timeout);
		if (!$resp) return true;
		if ($resp->faultCode()) {
                        $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
	      		return true;
		}
		$result = XML_RPC_Decode($resp->value());
		$i=0;
		foreach ($result['items'] as $item) {
			$i++;
			$_msg = "#{$item['item_id']}: \"{$item['title']}\" added by {$item['author']} (http://bordom.net/link/{$item['item_id']})\n";
			$this->ircClass->notice($line['fromNick'], $_msg);
                        if ($i>5) break;
		}
		$this->ircClass->log("Searched for '{$phrase}', found {$i} results.");
		return true;
	}

	public function priv_delcomment($line, $args) {
		$channel = $line['to'];
		if ($channel == $this->ircClass->getNick()) {
			return;
		}
                if (!$this->ircClass->hasModeSet($channel, $line['fromNick'], "vo")) {
			return;
		}
		if ($args['nargs'] == 0) {
			$this->ircClass->notice($line['fromNick'], "You must specify a comment id to delete.");
			return;
		}

		$comment_id = intval($args['arg1']);

		// first, get the comment
		$params = array(new XML_RPC_Value($comment_id, 'int'));
		$msg = new XML_RPC_Message('brax.comments.getComment', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($line['fromNick'],$resp->faultString());
			return;
		}

		$comment = XML_RPC_decode($resp->value());
		// ensure that nick is the comment owner
		if ($comment['author'] != $line['fromNick'] && empty($args['arg2'])) {
			$this->ircClass->notice($line['fromNick'], "Comment #{$comment_id} was posted by {$comment['author']}.  Use: !delcomment {$comment_id} --force");
			return;
		}

		// delete the comment
        $this->ircClass->log("Deleting comment.");

		$params = array(new XML_RPC_Value($comment_id, 'int'));
		$msg = new XML_RPC_Message('brax.comments.deleteComment', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($line['fromNick'],$resp->faultString());
			return;
		}

		$this->ircClass->notice($line['fromNick'], "Comment #{$comment_id} successfully removed from item #{$comment['item_id']}.");
	}

	public function priv_unset($line, $args) {
		$channel = $line['to'];
		if ($channel == $this->ircClass->getNick()) {
			return;
		}
        if (!$this->ircClass->hasModeSet($channel, $line['fromNick'], "vo")) {
			return;
		}
		if ($args['nargs'] == 0) {
			$this->ircClass->notice($line['fromNick'], "You must specify an item id to unset.");
			return;
		}
        $this->ircClass->log("Unsetting item.");

		$item_id = intval($args['arg1']);

		// first, get the item
		$params = array(new XML_RPC_Value($item_id, 'int'));
		$msg = new XML_RPC_Message('brax.items.getItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($line['fromNick'],$resp->faultString());
			return;
		}

		$item = XML_RPC_decode($resp->value());
		// ensure that nick is the item owner
		if ($comment['author'] != $line['fromNick'] && empty($args['arg2'])) {
			$this->ircClass->notice($line['fromNick'], "Item #{$item_id} was posted by {$item['author']}.  Use: !unset {$item_id} --force");
			return;
		}

		// unset the item
		$params = array(new XML_RPC_Value($item_id, 'int'));
		$msg = new XML_RPC_Message('brax.items.deleteSet', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($line['fromNick'],$resp->faultString());
			return;
		}

		$this->ircClass->notice($line['fromNick'], "Item #{$item_id} successfully removed from all sets.");
	}

	public function priv_feature($line, $args) {
		$channel = $line['to'];
		if ($channel == $this->ircClass->getNick()) {
			return;
		}
	    if (!$this->ircClass->hasModeSet($channel, $line['fromNick'], "vo")) {
			return;
		}
        $this->ircClass->log("Getting featured item.");

        $params = array();
		$msg = new XML_RPC_Message('brax.sources.getFeaturedItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($line['fromNick'],$resp->faultString());
			return;
		}

		$result = XML_RPC_decode($resp->value());
		$this->ircClass->privMsg($this->channel, "Featured item #{$result['item_id']}: {$result['title']}");
		$this->ircClass->privMsg($this->channel, "Posted by {$result['author']} on ".date("m/d/Y",$result['time']));
		$this->ircClass->privMsg($this->channel, "URL: http://bordom.net/link/{$result['item_id']}");
	}

	public function priv_addquote($line, $args) {
		$channel = $line['to'];
		if ($channel == $this->ircClass->getNick()) {
			return;
		}
        if (!$this->ircClass->hasModeSet($channel, $line['fromNick'], "vo")) {
            return;
        }
        if ($args['nargs'] == 0) {
            $this->ircClass->notice($line['fromNick'], "You must specify a quote to add.");
            return;
        }
        $this->ircClass->log("Adding quote.");
        $quote = trim(strstr($line['text'],' '));

        $params = array(
            new XML_RPC_Value($line['fromNick']), //author
            new XML_RPC_Value($quote), // quote
        );
		$msg = new XML_RPC_Message('brax.quotes.addQuote', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($line['fromNick'],$resp->faultString());
			return;
		}

		$result = XML_RPC_decode($resp->value());
        $this->ircClass->notice($line['fromNick'],"Quote {$result['quote_id']} has been added.");
	}

	public function priv_quote($line, $args) {
		$channel = $line['to'];
		if ($channel == $this->ircClass->getNick()) {
			return;
		}

        $this->ircClass->log("Getting random quote.");

        $params = array();
		$msg = new XML_RPC_Message('brax.quotes.getQuote', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($line['fromNick'],$resp->faultString());
			return;
		}

		$result = XML_RPC_decode($resp->value());
		$this->ircClass->privMsg($this->channel, "<{$result['quoted']}> {$result['quote']} (Quote #".BOLD.$result['quote_id'].BOLD." added by {$result['author']} on ".date("m/d/Y",$result['time']).")");
	}

	public function priv_help($line, $args) {
		$channel = $line['to'];

		if ($channel == $this->ircClass->getNick()) {
			return;
		}

		if ($args['nargs'] == 0) {
            $msg = new XML_RPC_Message('brax.getVersion');
        	$resp = $this->client->send($msg,$this->timeout);
            if (!$resp) return true;
            if ($resp->faultCode()) {
                $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
	            $this->ircClass->notice($line['fromNick'],$resp->faultString());
        	    return;
	        }
			$api_version = XML_RPC_decode($resp->value());
			$this->ircClass->privMsg($channel, "Bordom [{$this->version} (BRAX API {$api_version})] - see http://bordom.net/help");
			$chans = $this->ircClass->getMaintainedChannels();
			$channels = array();
			foreach ($chans as $index=>$C) {
				$channels[] = $C['CHANNEL'];
			}
			$this->ircClass->privMsg($channel, "Currently monitoring channels: " . join(", ",$channels));
		    $this->ircClass->log("Help requested.");
			return;
		} else {
			$cmd = $args['arg1'];
			switch ($cmd) {
				case "title": case "tit": $msg = "Usage: X: title <title> - Set item title to <title>"; break;
				case "url": $msg = "Usage: X: url <URL> - Change item URL to <URL>"; break;
				case "set": $msg = "Usage: X: set <item_id> [<item_id> <item_id>] - Add one or more items to an item set"; break;
				case "caption": case "cap": $msg = "Usage: X: caption <caption> - Set item caption to <caption>"; break;
				case "excerpt": case "exc": $msg = "Usage: X: excerpt <excerpt> - Set item excerpt to <excerpt>"; break;
				case "image": case "img": $msg = "Usage: X: image <URL> - Set item image to <URL>"; break;
				case "feature": $msg = "Usage: X: feature - Sets item X as featured item"; break;
				case "nick": $msg = "Usage: X: nick <nick> - Change item author to <nick>"; break;
				case "tag": $msg = "Usage: X: tag <word> - Add tag <word> to item"; break;
				case "untag": $msg = "Usage: X: untag <word> - Remove tag <word> from item"; break;
				case "hide": $msg = "Usage: X: hide - Mark item as hidden"; break;
				case "show": $msg = "Usage: X: show - Mark item as visible (unhidden)"; break;
				case "nsfw": $msg = "Usage: X: nsfw - Mark item as NOT safe for work"; break;
				case "sfw": $msg = "Usage: X: sfw - Mark item as SAFE for work"; break;
				case "bump": $msg = "Usage: X: bump - Bump item to top of page"; break;
				case "info": $msg = "Usage: X: info - Get info about an item"; break;
                                case "search": $msg = "Usage: !search <keyword> - Searches for keyword"; break;
				case "delcomment": $msg = "Usage: !delcomment <comment_id> - Deletes comment <comment_id>"; break;
				case "queue": case "q": $msg = "Usage: !queue - Print a summary of queued items"; break;
				case "quote": $msg = "Usage: !quote - Retrieve a random quote"; break;
				case "addquote": $msg = "Usage: !addquote <quote> - Adds a quote for yourself, or prefix with \"<nick>\" to quote someone else. Eg: !addquote <oblio> something oblio said"; break;
				default: $msg = "No help available for that command"; break;
			}
			$this->ircClass->privMsg($channel, $msg);
                        $this->ircClass->log("Help requested for command '{$cmd}'.");
		}
	}

	public function priv_queue($line, $args) {
		$channel = $line['to'];

		if ($channel == $this->ircClass->getNick()) {
			return;
		}

		if (!$this->ircClass->hasModeSet($channel, $line['fromNick'], "vo")) {
			return;
		}

		$params = array('queued' => 1,'hidden' => 0);
		$msg = new XML_RPC_Message('brax.items.getItems',array(XML_RPC_Encode($params)));
		$resp = $this->client->send($msg,$this->timeout);
                if (!$resp) return true;
		if (!$resp->faultCode()) {
			$result = XML_RPC_decode($resp->value());
			$count = $result['page_info']['num_items'];
			$this->ircClass->privMsg($this->channel, "There are {$count} items pending moderation. See http://bordom.net/queue/");
	                $this->ircClass->log("Queue summary requested.");
                        if ($count < 20) {
                		foreach ($result['items'] as $item) {
        	        		$this->ircClass->notice($line['fromNick'], "{$item['letter']}: {$item['title']} (by {$item['author']})\n");
        		        }
                        }
			return;
		}

		/*
		if ($args['arg1']=="--clear") {
			$params = array('queued' => 1,'hidden' => 0);
			$msg = new XML_RPC_Message('brax.items.getItems',array(XML_RPC_Encode($params)));
			$resp = $this->client->send($msg,$this->timeout);
                        if (!$resp) return true;
			if (!$resp->faultCode()) {
				$result = XML_RPC_decode($resp->value());
                		$count = $result['page_info']['num_items'];
				$this->ircClass->privMsg($this->channel, "Clearing {$count} items from the queue...");
		                foreach ($result['items'] as $item) {
		                	$params = array(
		                        	new XML_RPC_Value($item['item_id'],'int'),
		                        	new XML_RPC_Value(array(
		                        		'hidden' => new XML_RPC_Value(1,'int'),
		                        	), 'struct')
		                    	);
					$msg = new XML_RPC_Message('brax.items.updateItem', $params);
					$resp = $this->client->send($msg,$this->timeout);
                    if (!$resp) return true;
					if ($resp->faultCode()) {
						$this->ircClass->notice($nick,$resp->faultString());
						return;
		                    	}
		                }
				$this->ircClass->privMsg($this->channel, "All items ({$count}) cleared from queue.");
	                	$this->ircClass->log("Cleared queue.");
			}

		} elseif ($args['arg1']=="--approve") {
			$params = array('queued' => 1,'hidden' => 0);
			$msg = new XML_RPC_Message('brax.items.getItems',array(XML_RPC_Encode($params)));
			$resp = $this->client->send($msg,$this->timeout);
            if (!$resp) return true;
			if (!$resp->faultCode()) {
				$result = XML_RPC_decode($resp->value());
        			$count = $result['page_info']['num_items'];
				$this->ircClass->privMsg($this->channel, "Approving {$count} items from the queue...");
				foreach ($result['items'] as $item) {
					$time = time();
					$params = array(
						new XML_RPC_Value($item['item_id'],'int'),
                        			new XML_RPC_Value(array(
			                            'queued' => new XML_RPC_Value(0,'int'),
                        			    'time' => new XML_RPC_Value($time,'int'),
                            			    'updated' => new XML_RPC_Value($time,'int'),
                   				     ), 'struct')
                    				);
                    			$msg = new XML_RPC_Message('brax.items.updateItem', $params);
					$resp = $this->client->send($msg,$this->timeout);
                    if (!$resp) return true;
					if ($resp->faultCode()) {
						$this->ircClass->notice($nick,$resp->faultString());
						return;
                    			}
                		}
				$this->ircClass->privMsg($this->channel, "All items ({$count}) approved in queue.");
		                $this->ircClass->log("Cleared queue.");
			}
		} else {
			$this->ircClass->notice($line['fromNick'], "Usage: !queue [--clear|--approve]");
		}
		*/
	}

	/**
	 * Item commands
	 */

	function do_submit($url,$nick,$host) {
		$params = array(new XML_RPC_Value($url, 'string'));
		$msg = new XML_RPC_Message('brax.items.getItemByUrl', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
			// does not exist, add it
			$params = array(
				new XML_RPC_Value($nick), //author
				new XML_RPC_Value($url), //url
				new XML_RPC_Value("") //title
			);
			$msg = new XML_RPC_Message('brax.items.addItem', $params);
			$resp = $this->client->send($msg,$this->timeout);
            if (!$resp) return true;
			if ($resp->faultCode()) {
                #$this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
				$this->ircClass->notice($nick,$resp->faultString());
				return;
			}

			$result = XML_RPC_decode($resp->value());
			$this->ircClass->privMsg($this->channel, $result['letter'] . ": " . $result['title'] . " (Added #". BOLD . $result['item_id'] .  BOLD .").");
            $this->ircClass->log("Adding new item.");
			return;
		}

		// exists, update it
		$result = XML_RPC_decode($resp->value());
		$params = array(
			new XML_RPC_Value($result['item_id'],'int'),
			new XML_RPC_Value(array(
				'updated' => new XML_RPC_Value(time(),'int'),
				'reposted_by' => new XML_RPC_value($nick),
			), 'struct'),
			new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}
		$result = XML_RPC_decode($resp->value());
		$this->ircClass->privMsg($this->channel, $result['letter'] . ": " . $result['title'] . " (Updated #". BOLD . $result['item_id'] .  BOLD .").");
		$this->ircClass->privMsg($this->channel, "Item #{$result['item_id']} already existed, posted ".date("m/d/Y",$result['time'])." by {$result['author']}");
		$this->ircClass->privMsg($this->channel, "!insult {$nick}");
        $this->ircClass->log("Updating existing item.");
	}

	public function do_title($item_id,$nick,$title) {
        $this->ircClass->log("Setting title to item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
				'title' => new XML_RPC_Value($title),
                        ), 'struct'),
                        new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}
		$this->ircClass->notice($nick,"Item #{$item_id} successfully titled: {$title}");
	}

	public function do_author($item_id,$nick,$author) {
        $this->ircClass->log("Setting author on item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
                          'author' => new XML_RPC_Value($author),
                        ), 'struct'),
                        new XML_RPC_Value($nick) 
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}
		$this->ircClass->notice($nick,"Item #{$item_id} successfully changed to nick '{$author}'");
	}

	public function do_caption($item_id,$nick,$caption) {
        $this->ircClass->log("Setting caption to item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
                                'caption' => new XML_RPC_Value($caption),
                        ), 'struct'),
                        new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}

		if (empty($caption)) {
			$this->ircClass->notice($nick,"Caption removed from item #{$item_id} successfully.");
		} else {
			$this->ircClass->notice($nick,"Caption added to item #{$item_id} successfully.");
		}
	}

	public function do_excerpt($item_id,$nick,$excerpt) {
        $this->ircClass->log("Setting excerpt to item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
                                'excerpt' => new XML_RPC_Value($excerpt),
                        ), 'struct'),
                        new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}

		if (empty($excerpt)) {
			$this->ircClass->notice($nick,"Excerpt removed from item #{$item_id} successfully.");
		} else {
			$this->ircClass->notice($nick,"Excerpt added to item #{$item_id} successfully.");
		}
	}

	public function do_image($item_id,$nick,$image) {
        $this->ircClass->log("Setting image to item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
                          'image' => new XML_RPC_Value($image),
                        ), 'struct'),
                        new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}

		if (empty($image)) {
			$this->ircClass->notice($nick,"Image removed from item #{$item_id} successfully.");
		} else {
			$this->ircClass->notice($nick,"Image added to item #{$item_id} successfully.");
		}
	}

	public function do_tag($item_id,$nick,$tag) {
		$this->ircClass->log("Tagging item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
			new XML_RPC_Value($tag, 'string'),
			new XML_RPC_Value($nick, 'string')
		);
		$msg = new XML_RPC_Message('brax.items.addTag', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}
		$this->ircClass->notice($nick,"Tag(s) '{$tag}' added to item #{$item_id}.");
	}

	public function do_set($item_id,$nick,$set) {
		$this->ircClass->log("Adding set to item {$item_id}.");
                $set = trim($set);
                if (strstr($set," ")) {
                  $item_set = explode(" ",$set);
                } else {
                  $item_set = array($set);
                }
                foreach ($item_set as $other_item_id) {
                    if (preg_match("/^([a-zA-Z])$/",$other_item_id,$tmp)) {
		        // is a letter, get ID
                        $letter = strtolower($other_item_id);
			$params = array(new XML_RPC_Value($letter, 'string'));
			$msg = new XML_RPC_Message('brax.items.getIdByLetter', $params);
			$resp = $this->client->send($msg,$this->timeout);
                        if (!$resp) continue;
			if ($resp->faultCode()) {
                            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
                            continue;
			} else {
			    $other_item_id = $resp->value()->scalarval();
			}
                    }

                    $params = array(
	    		new XML_RPC_Value($item_id,'int'),
		    	new XML_RPC_Value($other_item_id, 'int'),
                    );
		  $msg = new XML_RPC_Message('brax.items.addSet', $params);
                  $resp = $this->client->send($msg,$this->timeout);
                  if (!$resp) return true;
                  if ($resp->faultCode()) {
                        $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
	    		$this->ircClass->notice($nick,$resp->faultString());
		    	return;
                  }
                }
		$this->ircClass->notice($nick,"Item #{$item_id} now set with items: {$set}.");
	}

	public function do_untag($item_id,$nick,$tag) {
          $this->ircClass->log("Deleting tag from item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
			new XML_RPC_Value($tag, 'string')
		);
		$msg = new XML_RPC_Message('brax.items.deleteTag', $params);
		$resp = $this->client->send($msg,$this->timeout);
                if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}
		$this->ircClass->notice($nick,"Tag '{$tag}' removed from item #{$item_id}.");
	}

	public function do_url($item_id,$nick,$url) {
		$this->ircClass->log("Setting URL to item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
                                'url' => new XML_RPC_Value($url),
                        ), 'struct'),
                        new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}

		$this->ircClass->notice($nick,"Item #{$item_id} URL successfully changed.");
	}

	public function do_comment($item_id,$nick,$comment) {
        $this->ircClass->log("Adding comment to item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
			new XML_RPC_Value($nick, 'string'),
			new XML_RPC_Value($comment, 'string'),
		);
		$msg = new XML_RPC_Message('brax.items.addComment', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}
		$result = XML_RPC_decode($resp->value());
		$this->ircClass->notice($nick, "Comment #{$result['comment_id']} added.");
	}

	public function do_hide($item_id,$nick) {
        $this->ircClass->log("Hiding item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
                                'hidden' => new XML_RPC_Value(1,'int'),
                        ), 'struct'),
                        new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}

		$this->ircClass->notice($nick, "Item #{$item_id} is now hidden");
	}

	public function do_show($item_id,$nick) {
        $this->ircClass->log("Showing item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
                                'hidden' => new XML_RPC_Value(0,'int'),
                        ), 'struct'),
                        new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}
		$this->ircClass->notice($nick, "Item #{$item_id} is now visible");
	}

	public function do_nsfw($item_id,$nick) {
        $this->ircClass->log("Setting item {$item_id} NSFW.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
                                'nsfw' => new XML_RPC_Value(1,'int'),
                        ), 'struct'),
                        new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}

		$this->ircClass->notice($nick, "Item #{$item_id} is now set NSFW");
	}

	public function do_sfw($item_id,$nick) {
        $this->ircClass->log("Setting item {$item_id} SFW.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
                                'nsfw' => new XML_RPC_Value(0,'int'),
                        ), 'struct'),
                        new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}

		$this->ircClass->notice($nick, "Item #{$item_id} is now set SFW");
	}

	public function do_bump($item_id,$nick) {
		$this->ircClass->log("Bumping item {$item_id}.");
		$params = array(
			new XML_RPC_Value($item_id,'int'),
                        new XML_RPC_Value(array(
                                'updated' => new XML_RPC_Value(time(),'int'),
                                'reposted_by' => new XML_RPC_Value($nick,'string'),
                        ), 'struct'),
                        new XML_RPC_Value($nick)
		);
		$msg = new XML_RPC_Message('brax.items.updateItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
        if (!$resp) return true;
		if ($resp->faultCode()) {
            $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}
		
		$this->ircClass->notice($nick, "Item #{$item_id} successfully bumped to the top.");
	}

	public function do_info($item_id,$nick) {
		$this->ircClass->log("Info for item {$item_id} requested.");
		$params = array(new XML_RPC_Value($item_id,'int'));
		$msg = new XML_RPC_Message('brax.items.getItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
                if (!$resp) return true;
		if ($resp->faultCode()) {
                        $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}
		$result = XML_RPC_decode($resp->value());
		$this->ircClass->notice($nick, "\"{$result['title']}\" [#{$result['item_id']}] was posted by {$result['author']} [{$result['source']}] on ".date("m/d/Y",$result['time']).".");
		$this->ircClass->notice($nick, "Item URL: http://bordom.net/view/{$result['item_id']}");
		$this->ircClass->notice($nick, "Link URL: http://bordom.net/link/{$result['item_id']}");
                if (!empty($result['excerpt'])) {
                        $this->ircClass->notice($nick, "Excerpt: {$result['excerpt']}");
                }
		$this->ircClass->notice($nick, "Content-Type: {$result['mimetype']} Hits: {$result['hits']} Views: {$result['views']} Comments: ".count($result['comments']));
	}

	public function do_feature($item_id,$nick) {
		$this->ircClass->log("Featuring item {$item_id}.");
		$params = array(new XML_RPC_Value($item_id,'int'));
		$msg = new XML_RPC_Message('brax.sources.featureItem', $params);
		$resp = $this->client->send($msg,$this->timeout);
                if (!$resp) return true;
      		if ($resp->faultCode()) {
                        $this->ircClass->log("Fault Code: " . $resp->faultCode() . "Fault Reason: " . $resp->faultString()); 
			$this->ircClass->notice($nick,$resp->faultString());
			return;
		}
		$result = XML_RPC_decode($resp->value());
		$this->ircClass->notice($nick, "Item #{$result['item_id']} has been featured for '{$result['source']}'.");
	}

    function clean_string($input) { 
        $search = array( 
            '/[\x60\x82\x91\x92\xb4\xb8]/i',            // single quotes 
            '/[\x84\x93\x94]/i',                        // double quotes 
            '/[\x85]/i',                                // ellipsis ... 
            '/[\x00-\x0d\x0b\x0c\x0e-\x1f\x7f-\x9f]/i'    // all other non-ascii 
        ); 
        $replace = array( 
            '\'', 
            '"', 
            '...', 
            '' 
        ); 
        return preg_replace($search,$replace,$input); 
    }

}
?>
